/**
 * @filename:DocumentInfoController 2025-04-27
 * @project starhub-schema  V1.0
 */
package com.starhub.api.document.controller;

import cn.hutool.core.bean.BeanUtil;
import com.starhub.engine.document.entity.DocumentInfo;
import com.starhub.engine.document.request.DocumentInfoBsRequest;
import com.starhub.engine.document.result.DocumentDealResult;
import com.starhub.engine.document.service.DocumentInfoService;
import com.starhub.api.document.token.DownloadToken;
import com.starhub.api.document.token.DownloadTokenManager;
import com.starhub.common.bean.ResultResp;
import com.starhub.common.security.util.SecurityUtils;
import com.starhub.common.sys.user.LoginUser;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

/**
 * <p>
 * 说明： 附件管理API接口层
 * </P>
 * 
 * @version: V1.0
 * @author: 孙赛赛-sss
 * @time 2025-04-27
 *
 */
@Api(value = "附件管理前台接口", tags = { "附件管理前台接口" }, description = "编写者:孙赛赛-sss")
@RestController
@RequestMapping("/api/starhub/document")
public class DocumentInfoController {
    @Autowired
    private DocumentInfoService documentService;

    @Autowired
    private DownloadTokenManager downloadTokenManager;

    /**
     * 日志
     */
    private static final Logger log = LoggerFactory.getLogger(DocumentInfoController.class);

    /**
     * 附件管理新增
     */
    @ApiOperation(value = "附件管理新增", notes = "附件管理新增")
    @PostMapping("/addDocumentInfo")
    public ResultResp addDocumentInfo(@RequestParam("file") MultipartFile file, DocumentInfo document) {
        ResultResp resultResp = null;
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            resultResp = ResultResp
                    .success(documentService.addDocumentInfo(new MultipartFile[] { file }, user, document));
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            resultResp = ResultResp.fail("接口异常",e);
        }
        return resultResp;
    }

    /**
     * 附件管理修改
     */
    @ApiOperation(value = "附件管理修改", notes = "附件管理修改")
    @PostMapping("/updateDocumentInfo")
    public ResultResp updateDocumentInfo(@RequestBody DocumentInfo document) {
        ResultResp resultResp = null;
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            resultResp = ResultResp.success(documentService.updateDocumentInfo(user, document));
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            resultResp = ResultResp.fail("接口异常",e);
        }
        return resultResp;
    }

    /**
     * 附件管理信息获取
     */
    @ApiOperation(value = "附件管理信息获取", notes = "附件管理信息获取")
    @GetMapping("/getDocumentInfoInfo/{id}")
    public ResultResp getDocumentInfoInfo(@PathVariable Long id) {
        ResultResp resultResp = null;
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            resultResp = ResultResp.success(documentService.getDocumentInfoInfo(user, id));
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            resultResp = ResultResp.fail("接口异常",e);
        }
        return resultResp;
    }

    /**
     * 附件管理物理删除
     */
    @ApiOperation(value = "附件管理物理删除", notes = "附件管理物理删除")
    @PostMapping("/deleteDocumentInfoRecord")
    public ResultResp deleteDocumentInfoRecord(@RequestBody DocumentInfoBsRequest documentInfoBsRequest) {
        ResultResp resultResp = null;
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            documentService.deleteDocumentInfoRecord(user, documentInfoBsRequest.getIds());
            resultResp = ResultResp.success("删除成功");
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            resultResp = ResultResp.fail("接口异常",e);
        }
        return resultResp;
    }

    /**
     * 附件管理列表获取
     */
    @ApiOperation(value = "附件管理列表获取", notes = "附件管理列表获取")
    @GetMapping("/getDocumentInfoList")
    public ResultResp getDocumentInfoList(@RequestBody DocumentInfo document) {
        ResultResp resultResp = null;
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            Map<String, Object> params = BeanUtil.beanToMap(document);
            resultResp = ResultResp.success(documentService.getDocumentInfoList(user, params));
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            resultResp = ResultResp.fail("接口异常",e);
        }
        return resultResp;
    }

    @ApiOperation(value = "目录下附件分页列表获取", notes = "目录下附件分页列表获取")
    @PostMapping("/getDocumentListByDir")
    public ResultResp getDocumentListByDir(@RequestBody DocumentInfoBsRequest documentInfoBsRequest) {
        ResultResp resultResp = null;
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            resultResp = ResultResp.success(documentService.getDocumentListByDir(documentInfoBsRequest));
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            resultResp = ResultResp.fail("接口异常",e);
        }
        return resultResp;
    }

    @SneakyThrows
    @GetMapping(value = "/download/{fileId}")
    @ApiOperation(value = "附件下载", notes = "附件下载")
    public void download(@PathVariable Long fileId, HttpServletResponse response) {
        try{
            LoginUser user = SecurityUtils.getCurrentUser();
            if(user==null){
                user = new LoginUser("1");
            }
            downloadFile(fileId, user, response);
        } catch (Exception e) {
            log.error("download error", e);
        }
    }

    /**
     * 根据附件ID获取附件内容
     * 
     * @param document
     * @return
     */
    @ApiOperation(value = "根据附件ID获取附件内容", notes = "根据附件ID获取附件内容")
    @PostMapping("/getContentByFileId")
    public ResultResp<DocumentDealResult> getContentByFileId(@RequestBody DocumentInfo document) {
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            return ResultResp.success(documentService.getContentByFileId(user, document.getId()));
        } catch (Exception e) {
            log.error("chat error", e);
            return ResultResp.fail(e.getMessage(),e);
        }
    }

    /**
     * 需要传递html、fileName、directoryId
     * 
     * @param document
     * @return
     */
    @ApiOperation(value = "根据Html生成文档", notes = "根据Html生成文档")
    @PostMapping("/converHtml2Word")
    public ResultResp converHtml2Word(@RequestBody DocumentInfoBsRequest document) {
        ResultResp resultResp = null;
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            resultResp = ResultResp.success(documentService.convertHtml2Word(user, document));
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            resultResp = ResultResp.fail("接口异常",e);
        }
        return resultResp;
    }

    /**
     * 高级HTML转DOCX接口 - 支持完整的样式保留
     * 支持字体、字号、行高、间距等排版样式的完整保留
     * 
     * @param document 包含html内容和文件信息的请求对象
     * @return 转换结果
     */
    @ApiOperation(value = "高级HTML转DOCX", notes = "将HTML转换为DOCX，完整保留所有排版样式")
    @PostMapping("/convertHtmlToDocxAdvanced")
    public ResultResp convertHtmlToDocxAdvanced(@RequestBody DocumentInfoBsRequest document) {
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            return ResultResp.success(documentService.convertHtmlToDocxAdvanced(user, document));
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            return ResultResp.fail(e.getMessage(), e);
        }
    }

    /**
     * 生成临时下载token
     */
    @ApiOperation(value = "生成临时下载token", notes = "生成临时下载token，有效期10分钟")
    @GetMapping("/generateDownloadToken/{fileId}")
    public ResultResp<String> generateDownloadToken(@PathVariable Long fileId) {
        try {
            LoginUser user = SecurityUtils.getCurrentUser();
            String token = downloadTokenManager.generateToken(fileId, user);
            return ResultResp.success(token);
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            return ResultResp.fail("生成下载token失败：" + e.getMessage() ,e);
        }
    }

    /**
     * 使用token下载文件
     */
    @SneakyThrows
    @GetMapping(value = "/downloadWithToken/{token}")
    @ApiOperation(value = "使用token下载文件", notes = "使用临时token下载文件")
    public void downloadWithToken(@PathVariable String token, HttpServletResponse response) {
        DownloadToken downloadToken = downloadTokenManager.validateToken(token);
        if (downloadToken == null) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "无效或已过期的下载token");
            return;
        }

        try {
            downloadFile(downloadToken.getFileId(), downloadToken.getUser(), response);
        } catch (Exception e) {
            log.error("downloadWithToken error", e);
        } finally {
            // 无论下载是否成功，都标记token为已使用并移除
            downloadTokenManager.removeToken(token);
        }

    }

    /**
     * 下载文件
     * 
     * @param fileId
     * @param user
     * @param response
     * @throws IOException
     */
    private void downloadFile(Long fileId, LoginUser user, HttpServletResponse response) throws IOException {
        Map<String, Object> result = documentService.downloadFile(fileId, user);
        if ((Boolean) result.get("status")) {
            if(result.containsKey("filePath") && result.containsKey("fileName")){
                String filePath = (String) result.get("filePath");
                String fileName = (String) result.get("fileName");
                fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
                fileName = StringUtils.replace(fileName, "/", "");
                fileName = StringUtils.replace(fileName, "%2F", "");
                fileName = StringUtils.replace(fileName, "+", "%20");

                int index = filePath.lastIndexOf(".");
                fileName = fileName + filePath.substring(index);
                Path path = Paths.get(filePath).toAbsolutePath().normalize();
                File file = path.toFile();
                if (!file.exists()) {
                    response.sendError(HttpServletResponse.SC_NOT_FOUND, "File not found.");
                    return;
                }
                String contentType = Files.probeContentType(path);
                if (contentType == null) {
                    contentType = "application/octet-stream";
                }
                response.setContentType(contentType);
                response.setContentLengthLong(file.length());
                response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

                try (FileInputStream inputStream = new FileInputStream(file);
                     ServletOutputStream outputStream = response.getOutputStream()) {
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    outputStream.flush();
                } catch (IOException e) {
                    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error reading the file.");
                }
            }
        }
    }
}